home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v10n05.arc / 2BOTH.ARC / 2FLOPPY.ARC / 2FLOPPY.C < prev    next >
Text File  |  1991-02-13  |  24KB  |  795 lines

  1. /* PROJECT....:  2FLOPPY.C
  2. ** FILE.......:  2floppy.c
  3. ** VERSION....:  1.0 (Turbo C++ 1.0 & MSC 5.0)
  4. ** AUTHOR.....:  Stephen D. Cooper
  5. ** NOTICE.....:  Copyright 1990 ZIFF Communications Co.
  6. **
  7. ** NOTES......:  This file contains those routines that are unique to
  8. **         2FLOPPY.EXE.
  9. **
  10. ** COMPILE....:  Turbo C ==> tcc -mc -O 2floppy.c fcommon.c
  11. **         MSC     ==> cl /AC 2floppy.c fcommon.c
  12. */
  13.  
  14. /********************************************************************
  15. **    INCLUDE FILES                           **
  16. ********************************************************************/
  17.  
  18. #define MAIN_FILE
  19.  
  20. #include <conio.h>
  21. #include <dos.h>
  22. #include <signal.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <sys\stat.h>
  26. #include "2flo_err.h"
  27. #include "compiler.h"
  28. #include "fcommon.h"
  29.  
  30. /********************************************************************
  31. **    #define CONSTANTS                             **
  32. ********************************************************************/
  33.  
  34. #define FIELD_LIST_SIZE 72        /* Allows max (18 * 4)
  35.                        format field list */
  36.  
  37. /********************************************************************
  38. **    GLOBAL VARIABLES                              **
  39. ********************************************************************/
  40.  
  41. char disk_field_list[FIELD_LIST_SIZE];    /* Format field list */
  42.  
  43. int beep_flag = TRUE;            /* Beep? y/n */
  44. int multiple_flag = FALSE;        /* Multiple copies? */
  45. int repetitions = 1;            /* # of repetitions */
  46. int verify_flag = TRUE;            /* Verify copy? */
  47.  
  48. unsigned drivenumber;            /* Target floppy drive */
  49. unsigned sector_size_code;        /* Format track sector size */
  50.  
  51. DISKSTATS dstats;
  52.  
  53. /********************************************************************
  54. **    FUNCTION DECLARATIONS                          **
  55. ********************************************************************/
  56.  
  57. int ask_permission(int flp_num);
  58. int check_2file(void);
  59. int check_reps(char *repnum);
  60. int format_track(int track, int head, DISKSTATS *dstats);
  61. int handle_flags(char *arg);
  62. int process_file(void);
  63. int process_args(int argc, char *argv[]);
  64. int verify_buffs(int track, int head, char *buff1, char *buff2,
  65.                  int buffsize);
  66. int sector_write(union REGS *inregs, union REGS *outregs, char *buff,
  67.                  DISKSTATS *dstats);
  68. int write_sectors(int track, int head, DISKSTATS *dstats, char *buff);
  69.  
  70. void fanfare(void);
  71. void help(void);
  72.  
  73. /********************************************************************
  74. *********************************************************************
  75. **    CODE STARTS                             **
  76. *********************************************************************
  77. ********************************************************************/
  78.  
  79. /********************************************************************
  80. ** FUNCTION....:  main()                       **
  81. ********************************************************************/
  82.  
  83. void main(int argc, char *argv[])
  84. {
  85.     int floppynum = 1;
  86.     int retval;            /* Value returned by funcs */
  87.  
  88.     /*
  89.     ** Install our ctrl-break handler
  90.     ** and our hardware error handler
  91.     */
  92.     signal(SIGINT, ctrlbrk_handler);
  93.     HARDERR(harderr_handler);
  94.  
  95.     fanfare();            /* Strut our stuff */
  96.  
  97.     /*
  98.     ** Process and error-check command line
  99.     */
  100.     if((retval = process_args(argc, argv)) != 0)
  101.         err_exit(retval);
  102.  
  103.     /*
  104.     ** Check the file to make sure that it is a 2FILE file
  105.     */
  106.     if((retval = check_2file()) != 0)
  107.         err_exit(retval);
  108.  
  109.     /*
  110.     ** Main processing
  111.     */
  112.     while(repetitions-- > 0)
  113.     {
  114.         if((retval = ask_permission(floppynum++)) != 'Y')
  115.             err_exit(ERR_USER_ABORT);
  116.  
  117.         if((retval = process_file()) != 0)
  118.             err_exit(retval);
  119.     }
  120.  
  121.     /*
  122.     ** Clean-up and go home
  123.     */
  124.     fclose(fileptr);
  125.     free(read_buff);
  126.     printf("Program completed\n\n");
  127.     exit(ERR_NO_ERRORS);
  128. }
  129.  
  130. /*********************************************************************
  131. ** FUNCTION....: ask_permission()                    **
  132. ** RETURNS.....: Either:  'Y' - User wants to proceed            **
  133. **              'N' - User wants to quit the program      **
  134. ** NOTES.......: ask_permission() displays some useful statistics   **
  135. **         about the file and the target disk, tells the user **
  136. **         that processing is about to commence, and asks the **
  137. **         user whether to continue or not.                   **
  138. *********************************************************************/
  139.  
  140. int ask_permission(int flp_num)
  141. {
  142.     int retval;
  143.  
  144.     printf("\nSource file.............:  %s\n", filename);
  145.     printf("Destination floppy drive:  %c: ", drivenumber + 'A');
  146.     printf("(%u sides, %u tracks, %u sectors per track)\n",
  147.            dstats.sides, dstats.numtracks, dstats.numsectors);
  148.  
  149.     printf("\nPlease insert floppy disk ");
  150.     if(multiple_flag)
  151.         printf("%d ", flp_num);
  152.     printf("into drive %c:\n", drivenumber + 'A');
  153.  
  154.     printf("\nAbout to start copying.  ");
  155.  
  156.     if(beep_flag)
  157.         putchar(0x07);
  158.  
  159.     retval = continue_yn();
  160.  
  161.     printf("\n\n");
  162.  
  163.     return(retval);
  164. }
  165.  
  166. /*********************************************************************
  167. ** FUNCTION....: check_2file()                        **
  168. ** RETURNS.....: ERR_NO_ERRORS       = Function successful          **
  169. **         ERR_BAD_FILE_SIZE   = The file is probably corrupt **
  170. **         ERR_BAD_HEADER      = The file probably wasn't a   **
  171. **                       2FILE file.            **
  172. **         ERR_CANT_FIND_FILE  = Couldn't get statistics         **
  173. **                       about the file (namely the   **
  174. **                       file's size).            **
  175. **         ERR_CANT_OPEN_INPUT = fopen() could'nt open the    **
  176. **                       file.                **
  177. **         ERR_READING_FILE    = Problems reading file.        **
  178. **         ERR_USER_ABORT         = The user elected not to        **
  179. **                       continue after a critical    **
  180. **                       error.                **
  181. ** NOTES.......: check_2file() checks out the file named on the        **
  182. **         command line to make sure that it isn't corrupt or **
  183. **         a non-2FILE file.  It also fills in our DISKSTATS  **
  184. **         structure so that other parts of the program can   **
  185. **         proceed.                        **
  186. *********************************************************************/
  187.  
  188. int check_2file(void)
  189. {
  190.     char inits[3];            /* File header initials */
  191.     int  retval;            /* Func return value */
  192.     unsigned long file_size;    /* Size the file should be */
  193.     struct stat statbuff;        /* To get file size */
  194.  
  195.     /*
  196.     ** Get file statistics (we need the size of the file)
  197.     */
  198.     do
  199.     {
  200.         if((retval = stat(filename, &statbuff)) != 0)
  201.             return(ERR_CANT_FIND_FILE);
  202.     } while(harderr_status == HARDERR_RETRY);
  203.  
  204.     if(harderr_status == HARDERR_ABORT)
  205.         err_exit(ERR_USER_ABORT);
  206.  
  207.     /*
  208.     ** Open the file
  209.     */
  210.     do
  211.     {
  212.         if((fileptr = fopen(filename, "rb")) == NULL)
  213.             err_exit(ERR_CANT_OPEN_INPUT);
  214.     } while(harderr_status == HARDERR_RETRY);
  215.  
  216.     if(harderr_status == HARDERR_ABORT)
  217.         err_exit(ERR_USER_ABORT);
  218.  
  219.     prg_status = HARDERR_CRITICAL;
  220.  
  221.     /*
  222.     ** Check the header initials -- first 3 bytes
  223.     */
  224.     retval = fread(inits, 3 * sizeof(char), 1, fileptr);
  225.     if(retval != 1)
  226.         return(ERR_READING_FILE);
  227.  
  228.     if(inits[0] != INI_1 || inits[1] != INI_2 || inits[2] != INI_3)
  229.         return(ERR_BAD_HEADER);
  230.  
  231.     /*
  232.     ** Check file header disk stats
  233.     */
  234.     retval = fread(&dstats, sizeof(dstats), 1, fileptr);
  235.     if(retval != 1)
  236.         return(ERR_READING_FILE);
  237.  
  238.     if(dstats.drivenum != 0 && dstats.drivenum != 1)
  239.         return(ERR_BAD_HEADER);
  240.     if(dstats.sides != 1 && dstats.sides != 2)
  241.         return(ERR_BAD_HEADER);
  242.     if(dstats.numtracks != 40 && dstats.numtracks != 80)
  243.         return(ERR_BAD_HEADER);
  244.  
  245.     /*
  246.     ** We need to reset dstats.drivenum to the drivenumber
  247.     ** that we got from the command line.  (We did this in
  248.     ** process_args so that check_filename() would work
  249.     ** correctly.  Then we overwrote the structure so that
  250.     ** we could check the 2FILE file (in this function).
  251.     ** Redundant?  Maybe, but it works.)
  252.     */
  253.     dstats.drivenum = drivenumber;
  254.  
  255.     /*
  256.     ** If we've made it this far, chances are VERY GOOD that we
  257.     ** have a true-blue 2FILE file.  If so, we've filled in our
  258.     ** structure so that the rest of the program can continue.
  259.     ** The only other check we need to make is the file's size.
  260.     ** We check this to make sure that the copy we make will be
  261.     ** good (if something happened while 2FILE was operating and
  262.     ** the file is not the correct size, the resulting 2FLOPPY
  263.     ** disk would be bad).
  264.     */
  265.  
  266.     /*
  267.     ** Calculate the size the file should be
  268.     */
  269.     file_size = (unsigned long)dstats.sectorsize;
  270.     file_size *= (unsigned long)dstats.numsectors;
  271.     file_size *= (unsigned long)dstats.numtracks;
  272.     file_size *= (unsigned long)dstats.sides;
  273.     file_size += (unsigned long)(sizeof(dstats) + 3);
  274.  
  275.     /*
  276.     ** Compare the actual size of the file and
  277.     ** compare with what it should be.  If it isn't
  278.     ** the right size, tell the user the sizes involved.
  279.     */
  280.     if(statbuff.st_size != file_size)
  281.     {
  282.         printf("Size (in bytes) the file should be....:  ");
  283.         printf("%lu\n", file_size);
  284.         printf("Size (in bytes) the file actually is..:  ");
  285.         printf("%lu\n", statbuff.st_size);
  286.         return(ERR_BAD_FILE_SIZE);
  287.     }
  288.  
  289.     return(ERR_NO_ERRORS);
  290. }
  291.  
  292. /*********************************************************************
  293. ** FUNCTION....: check_reps()                        **
  294. ** RETURNS.....: The int value of the string given on the command   **
  295. **         line or -1 if atoi() returns less than 1.        **
  296. ** NOTES.......: check_reps() converts a string to an integer and   **
  297. **         checks the value for less than 1.            **
  298. *********************************************************************/
  299.  
  300. int check_reps(char *repnum)
  301. {
  302.     int retval;
  303.  
  304.     retval = atoi(repnum);
  305.  
  306.     return(retval < 1 ? -1 : retval);
  307. }
  308.  
  309. /*********************************************************************
  310. ** FUNCTION....: fanfare()                                  **
  311. ** RETURNS.....: nothing                        **
  312. ** NOTES.......: fanfare() displays a copyright and author notice   **
  313. **         notice.                        **
  314. *********************************************************************/
  315.  
  316. void fanfare(void)
  317. {
  318.     cputs("\r\n2FLOPPY version 1.0 Copyright 1990 ZIFF "
  319.           "Communications Co.\r\n");
  320.     cputs("PC Magazine ■ Stephen D. Cooper.\r\n\n");
  321. }
  322.  
  323. /********************************************************************
  324. ** FUNCTION....: format_track()                          **
  325. **                                   **
  326. ** PARAMETERS..: int track   = The track number to format       **
  327. **         int head    = The head (side) to format       **
  328. **         DISKSTATS *dstats = A structure that contains       **
  329. **                 statistics about the disk       **
  330. **                                   **
  331. ** RETURNS.....: ERR_NO_ERRORS      = Function successful           **
  332. **         ERR_FORMATTING_DISK  = Problems formatting       **
  333. **         ERR_HARD_DISK_FORMAT = The programmer asked the   **
  334. **                    function to format a track **
  335. **                    on a hard disk (this       **
  336. **                    function only formats       **
  337. **                    floppy disks).           **
  338. **                                   **
  339. ** NOTES.......: format_track() calls the bios to format a track   **
  340. **         on a floppy disk.                   **
  341. ********************************************************************/
  342.  
  343. int format_track(int track, int head, DISKSTATS *dstats)
  344. {
  345.     char *fieldlist = disk_field_list;    /* Format field list */
  346.     int  try_cntr = 3;            /* If failure, try 3 times */
  347.     int  retval;
  348.     int  sector;                /* Sector loop counter */
  349.     struct SREGS sregs;
  350.     union REGS inregs, outregs;
  351.  
  352.     /*
  353.     ** WE DON'T DO HARD DISKS!
  354.     */
  355.     if(dstats->drivenum < 0 || dstats->drivenum > 1)
  356.         return(ERR_HARD_DISK_FORMAT);
  357.  
  358.     for(sector = 1; sector <= dstats->numsectors; sector++)
  359.     {
  360.         *fieldlist++ = track;
  361.         *fieldlist++ = head;
  362.         *fieldlist++ = sector;
  363.         *fieldlist++ = sector_size_code;
  364.     }
  365.  
  366.     inregs.h.ah = BIOSFUNC_FORMAT;
  367.     inregs.h.ch = track;
  368.     inregs.h.dh = head;
  369.     inregs.h.dl = dstats->drivenum;
  370.     inregs.x.bx = FP_OFF((char far *)disk_field_list);
  371.  
  372.     do
  373.     {
  374.         sregs.es = FP_SEG((char far *)disk_field_list);
  375.  
  376.         int86x(BIOS_DISK, &inregs, &outregs, &sregs);
  377.         if(outregs.h.ah)
  378.             if((retval = reset_drive(dstats->drivenum)) != 0)
  379.                 return(retval);
  380.     } while(outregs.h.ah && --try_cntr > 0);
  381.  
  382.     if(outregs.h.ah)
  383.         return(ERR_FORMATTING_DISK);
  384.  
  385.     return(ERR_NO_ERRORS);
  386. }
  387.  
  388. /*********************************************************************
  389. ** FUNCTION....: handle_flags()                        **
  390. **                                    **
  391. ** PARAMETERS..: char *arg = The command line argument to handle    **
  392. **                                    **
  393. ** RETURNS.....: ERR_NO_ERRORS       = function successful        **
  394. **         ERR_BAD_REPETITIONS = The number of repetitions    **
  395. **                       given on the command line    **
  396. **                       was less than 1.            **
  397. **         ERR_UNKNOWN_ARG     = The argument on the command  **
  398. **                       line is invalid.            **
  399. **                                    **
  400. ** NOTES.......: handle_flags() looks at the passed argument for    **
  401. **         proper form and content and sets a global flag        **
  402. **         accordingly.                        **
  403. *********************************************************************/
  404.  
  405. int handle_flags(char *arg)
  406. {
  407.     int retval = ERR_NO_ERRORS;
  408.  
  409.     if(*arg == '/')
  410.     {
  411.         if(*(arg + 1) >= '0' && *(arg + 1) <= '9')
  412.         {
  413.             if((repetitions = check_reps(++arg)) == -1)
  414.                 retval = ERR_BAD_REPETITIONS;
  415.             else
  416.                 multiple_flag = TRUE;
  417.         }
  418.         else if(*(arg + 1) == 'Q' || *(arg + 1) == 'q')
  419.             beep_flag = FALSE;
  420.         else if(*(arg + 1) == 'V' || *(arg + 1) == 'v')
  421.             verify_flag = FALSE;
  422.         else
  423.             retval = ERR_UNKNOWN_ARG;
  424.     }
  425.     else
  426.         retval = ERR_UNKNOWN_ARG;
  427.  
  428.     return(retval);
  429. }
  430.  
  431. /*********************************************************************
  432. ** FUNCTION....: help()                            **
  433. **                                    **
  434. ** PARAMETERS..: none                            **
  435. **                                    **
  436. ** RETURNS.....: nothing                        **
  437. **                                    **
  438. ** NOTES.......: help() displays the program's command line help    **
  439. **         screen.                        **
  440. *********************************************************************/
  441.  
  442. void help(void)
  443. {
  444.     char spc = ' ';
  445.  
  446.     printf("Syntax:  2FLOPPY drive filename [/#] [/q] [/v]\n\n");
  447.  
  448.     printf("Where:   drive    = The name of the destination floppy ");
  449.     printf("disk drive.\n\n");
  450.  
  451.     printf("%8c filename = The name of the source file.  The ", spc);
  452.     printf("current drive is the\n");
  453.     printf("%19c default drive.  .FLP is the default ", spc);
  454.     printf("extension.  The drive\n");
  455.     printf("%19c that contains filename must be different ", spc);
  456.     printf("from the\n");
  457.     printf("%19c destination floppy drive.\n\n", spc);
  458.  
  459.     printf("%8c /#%7c= The number of floppy disk copies ", spc, spc);
  460.     printf("you wish to create.\n");
  461.     printf("%8c /q%7c= Quiet option (program won't beep ", spc, spc);
  462.     printf("when asking for a\n");
  463.     printf("%19c floppy disk).\n", spc);
  464.     printf("%8c /v%7c= No verify option (program won't ", spc, spc);
  465.     printf("verify the copy).\n\n");
  466.  
  467.     printf("Note:    The last three parameters (/#, /q, /v) are ");
  468.     printf("all optional and can be\n");
  469.     printf("%8c given in any order.  The filename, /q, and /v ", spc);
  470.     printf("parameters can be\n");
  471.     printf("%8c either upper case or lower case.\n\n", spc);
  472. }
  473.  
  474. /*********************************************************************
  475. ** FUNCTION....: process_args()                        **
  476. **                                    **
  477. ** PARAMETERS..: int argc     = same as main() int argc            **
  478. **         char *argv[] = same as main() char *argv[]         **
  479. **                                    **
  480. ** RETURNS.....: ERR_NO_ERRORS      = function successful                **
  481. **         Any other value = An error was encountered.        **
  482. **                                    **
  483. ** NOTES.......: process_args() processes all command line args        **
  484. *********************************************************************/
  485.  
  486. int process_args(int argc, char *argv[])
  487. {
  488.     int retval;                /* Value returned by funcs */
  489.  
  490.     /*
  491.     ** Check the number of DOS command line arguments
  492.     */
  493.     if((retval = check_numargs(argc, 3, 6)) != 0)
  494.     {
  495.         help();
  496.         return(retval);
  497.     }
  498.  
  499.     /*
  500.     ** Check the first parameter --
  501.     ** must be "A:" or "B:" (case insignificant)
  502.     */
  503.     retval = floppyletter_2_number(&drivenumber, argv[1]);
  504.     if(retval != 0)
  505.     {
  506.         help();
  507.         return(retval);
  508.     }
  509.  
  510.     /*
  511.     ** Check the second parameter -- Must be a filename
  512.     ** (default drive is current, default extension is .FLP)
  513.     */
  514.     dstats.drivenum = drivenumber;
  515.     if((retval = check_filename(filename, argv[2], &dstats)) != 0)
  516.     {
  517.         help();
  518.         return(retval);
  519.     }
  520.  
  521.     /*
  522.     ** Check and process other command line arguments (/N /Q /V)
  523.     */
  524.     while(--argc > 2)
  525.         if((retval = handle_flags(argv[argc])) != 0)
  526.         {
  527.             help();
  528.             return(retval);
  529.         }
  530.  
  531.     return(ERR_NO_ERRORS);
  532. }
  533.  
  534. /*********************************************************************
  535. ** FUNCTION....: process_file()                            **
  536. **                                    **
  537. ** PARAMETERS..: none                            **
  538. **                                    **
  539. ** RETURNS.....: ERR_NO_ERRORS      = function successful        **
  540. **         ERR_BAD_SECTORSIZE = The sector size in DISKSTATS  **
  541. **                      is one we're not set up for.  **
  542. **         ERR_MEMORY         = Can't malloc() enough memory  **
  543. **                      to complete processing.        **
  544. **                                    **
  545. ** NOTES.......: process_file() is the main workhorse for the prg.  **
  546. **         it calls on other functions to read, format        **
  547. **         write, and verify and displays the progress of the **
  548. **         program to the user.                    **
  549. *********************************************************************/
  550.  
  551. int process_file(void)
  552. {
  553.     char     *vbuff;
  554.     int       retval;
  555.     int       head, track;
  556.     int         xhead, xtrack, yloc;
  557.     unsigned buffsize;
  558.  
  559. #if !defined(TURBO_C)
  560.     struct rccoord cursorpos;
  561. #endif
  562.  
  563.     switch(dstats.sectorsize)
  564.     {
  565.         case 128:
  566.             sector_size_code = 0;
  567.             break;
  568.         case 256:
  569.             sector_size_code = 1;
  570.             break;
  571.         case 512:
  572.             sector_size_code = 2;
  573.             break;
  574.         case 1024:
  575.             sector_size_code = 3;
  576.             break;
  577.         default:
  578.             fclose(fileptr);
  579.             return(ERR_BAD_SECTORSIZE);
  580.     }
  581.  
  582.     /*
  583.     ** Get our read buffer
  584.     */
  585.     buffsize = dstats.sectorsize * dstats.numsectors;
  586.     buffsize *= sizeof(char);
  587.  
  588.     if((read_buff = (char *)malloc(buffsize)) == 0)  /* Main buff */
  589.         return(ERR_MEMORY);
  590.  
  591.     if((vbuff = (char *)malloc(buffsize)) == 0)    /* Verify buff */
  592.         return(ERR_MEMORY);
  593.  
  594.     /*
  595.     ** Rewind the file to the byte just past the file header
  596.     */
  597.     fseek(fileptr, (long)(sizeof(dstats) + 3), SEEK_SET);
  598.  
  599.     /*
  600.     ** Read file, format floppy and write floppy
  601.     */
  602.     printf("\n");
  603. #if defined(TURBO_C)
  604.     xhead = wherex() + 18;
  605.     yloc = wherey();
  606. #else
  607.     cursorpos = _gettextposition();
  608.     xhead = cusrorpos.col + 18;
  609.     yloc = cusrorpos.row;
  610. #endif
  611.     xtrack = xhead + 9;
  612.     printf("Formatting:  head 0, track 00");
  613.     for(track = 0; track < dstats.numtracks; track++)
  614.     {
  615.         GOTOXY(xtrack, yloc);
  616.         printf("%2u", track);
  617.         for(head = 0; head < dstats.sides; head++)
  618.         {
  619.  
  620.             GOTOXY(xhead, yloc);
  621.             printf("%1u", head);
  622.  
  623.             GOTOXY(1, yloc);
  624.             printf("Reading   ");
  625.             retval = fread(read_buff, buffsize, 1, fileptr);
  626.             if(retval != 1)
  627.             {
  628.                 retval = ERR_READING_FILE;
  629.                 break;
  630.             }
  631.  
  632.             GOTOXY(1, yloc);
  633.             printf("Formatting");
  634.             if((retval = format_track(track, head, &dstats)) != 0)
  635.                 break;
  636.  
  637.             GOTOXY(1, yloc);
  638.             printf("Writing   ");
  639.             retval = write_sectors(track, head, &dstats, read_buff);
  640.             if(retval != 0)
  641.                 break;
  642.  
  643.             if(verify_flag)
  644.             {
  645.                 GOTOXY(1, yloc);
  646.                 printf("Verifying :");
  647.                 retval = verify_buffs(track, head, read_buff, vbuff,
  648.                                       buffsize);
  649.                 if(retval != 0)
  650.                     break;
  651.             }
  652.         }
  653.         if(retval != ERR_NO_ERRORS)
  654.             break;
  655.     }
  656.  
  657.     /*
  658.     ** Clean up and return
  659.     */
  660.     printf("\n");
  661.     free(vbuff);
  662.     free(read_buff);
  663.     return(retval);
  664. }
  665.  
  666. /********************************************************************
  667. ** FUNCTION....: verify_buffs()                          **
  668. **                                   **
  669. ** PARAMETERS..: int track    = The track number to verify       **
  670. **         int head     = The head number to verify          **
  671. **         char *buff1  = The original memory buffer         **
  672. **         char *buff2  = The verify buffer to read into     **
  673. **         int buffsize = The size of the buffers            **
  674. **                                   **
  675. ** RETURNS.....: ERR_NO_ERRORS = Good verify               **
  676. **         ERR_BAD_VERIFY = Bad verify                       **
  677. **                                   **
  678. ** NOTES.......: verify_buffs() reads a track into a buffer and       **
  679. **         compares that buffer with the buffer that was       **
  680. **         used to write the track.               **
  681. ********************************************************************/
  682.  
  683. int verify_buffs(int track, int head, char *buff1, char *buff2,
  684.                  int buffsize)
  685. {
  686.     int retval = ERR_NO_ERRORS;
  687.  
  688.     if((retval = read_sectors(track, head, buff2, &dstats)) == 0)
  689.         if(memcmp(buff1, buff2, buffsize))
  690.             retval = ERR_BAD_VERIFY;
  691.  
  692.     return(retval);
  693. }
  694.  
  695. /********************************************************************
  696. ** FUNCTION....: write_sectors()                      **
  697. **                                   **
  698. ** PARAMETERS..: int track  = The track to write               **
  699. **         int head   = The head to write                    **
  700. **         DISKSTATS *dstats = The disk statistics structure **
  701. **         char *buff = The buffer to write to disk          **
  702. **                                   **
  703. ** RETURNS.....: ERR_NO_ERRORS = Track written successfully       **
  704. **         Any other value = Problems writing track       **
  705. **                                   **
  706. ** NOTES.......: write_sectors() uses the BIOS to write a buffer   **
  707. **         to a track on a disk.                   **
  708. ********************************************************************/
  709.  
  710. int write_sectors(int track, int head, DISKSTATS *dstats, char *buff)
  711. {
  712.     int retval;
  713.     unsigned char *newbuff;
  714.     union REGS inregs, outregs;
  715.  
  716.     inregs.h.ah = BIOSFUNC_WRITE_SECTOR;
  717.     if(dstats->numsectors > 9)
  718.         inregs.h.al = 9;
  719.     else
  720.         inregs.h.al = dstats->numsectors;
  721.     inregs.h.ch = track;
  722.     inregs.h.cl = 1;            /* Start with sector 1 */
  723.     inregs.h.dh = head;
  724.     inregs.h.dl = dstats->drivenum;
  725.     inregs.x.bx = FP_OFF((char far *)buff);
  726.  
  727.     retval = sector_write(&inregs, &outregs, buff, dstats);
  728.     if(retval != 0)
  729.         return(retval);
  730.  
  731.     if(dstats->numsectors > 9)
  732.     {
  733.         inregs.h.al = dstats->numsectors - 9;
  734.         inregs.h.cl = 10;
  735.         newbuff = buff + (9 * dstats->sectorsize);
  736.         inregs.x.bx = FP_OFF((char far *)newbuff);
  737.         retval = sector_write(&inregs, &outregs, newbuff, dstats);
  738.     }
  739.     return(retval);
  740. }
  741.  
  742. /********************************************************************
  743. ** FUNCTION....: sector_write()                                  **
  744. **                                   **
  745. ** PARAMETERS..: union REGS *inregs  = int86x() union ALREADY       **
  746. **                          FILLED IN.           **
  747. **         union REGS *outregs = int86x() union ALREADY       **
  748. **                          FILLED IN.           **
  749. **         char *buff           = The buffer to write to disk **
  750. **         DISKSTATS *dstats   = Statistics about the disk   **
  751. **                                   **
  752. ** RETURNS.....: ERR_NO_ERRORS       = function successful       **
  753. **         ERR_WRITING_SECTORS = Problems writing to track   **
  754. **                                   **
  755. ** NOTES.......: sector_write() calls the BIOS to write char *buff **
  756. **         to a track on a disk.                   **
  757. **                                   **
  758. **         SPECIAL NOTE:  This function exists because there  **
  759. **                is a bug in the BIOS that crashes  **
  760. **                whenever you try to write sectors  **
  761. **                9 and 10 to a track on a       **
  762. **                high-density disk.  With these       **
  763. **                disks, write_sectors() calls this  **
  764. **                routine twice (other disks only       **
  765. **                once), once for sectors 1-9 and       **
  766. **                the second time for sectors 10-?   **
  767. ********************************************************************/
  768.  
  769. int sector_write(union REGS *inregs, union REGS *outregs, char *buff,
  770.                  DISKSTATS *dstats)
  771. {
  772.     int retval, try_cntr = 3;
  773.     struct SREGS sregs;
  774.  
  775.     /*
  776.     ** Try 3 times if not successful
  777.     */
  778.     do
  779.     {
  780.         sregs.es = FP_SEG((char far *)buff);
  781.         int86x(BIOS_DISK, inregs, outregs, &sregs);
  782.         if(outregs->h.ah)
  783.             if((retval = reset_drive(dstats->drivenum)) != 0)
  784.                 return(retval);
  785.     } while(outregs->h.ah && --try_cntr > 0);
  786.  
  787.     return(outregs->h.ah == 0 ? 0 : ERR_WRITING_SECTORS);
  788. }
  789.  
  790. /******************************
  791. *******************************
  792. **** END OF FILE 2floppy.c ****
  793. *******************************
  794. ******************************/
  795.